﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Biblioteca.Models;
using System.Data;


    public class MyRoleProvider: RoleProvider
    {
        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            //Asumo que se trata de un unico usuario que se le asigna un unico rol.
            using (BibliotecaStore db = new BibliotecaStore())
            {
                //Busco el usuario en cuestion
                string us = usernames[0];
                Cuenta cta = db.Cuentas.Single(c => c.Usuario == us);
                CuentaUsuario cta_us = db.CuentaUsuarios.Single(t => t.Cuenta == cta.IdCuenta);
                Usuario user = db.Usuarios.Single(u => u.IdUsuario == cta_us.Usuario);

                //Busco el id del Rol a agregar
                string ro = roleNames[0];
                TipoUsuario tipo = db.TipoUsuarios.Single(r => r.Descripcion == ro);

                //Al usuario le seteo el nuevo tipo.
                user.Tipo = tipo.IdTipoUser;
                db.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
                db.SaveChanges();
            }

        }

        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override void CreateRole(string roleName)
        {
            //Se crea el rol si no existe ya uno con el mismo nombre.
            using (BibliotecaStore db = new BibliotecaStore())
            {
                TipoUsuario rol = db.TipoUsuarios.Single(r => r.Descripcion == roleName);

                if (rol == null)
                {
                    TipoUsuario nuevo = new TipoUsuario();
                    nuevo.Descripcion = roleName;

                    db.TipoUsuarios.AddObject(nuevo);
                    db.SaveChanges();
                }
                else
                {
                    //Ya existe un rol con ese nombre, no se hace nada.
                }
            }
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            //Asumo que existen 2 roles fijos, Administrador id=1 y Socio Biblioteca id=2, que no se pueden eliminar.
            using (BibliotecaStore db = new BibliotecaStore())
            {
                TipoUsuario rol = db.TipoUsuarios.Single(r => r.Descripcion == roleName);

                if (rol.IdTipoUser != 1 && rol.IdTipoUser != 2)
                {
                    db.TipoUsuarios.DeleteObject(rol);
                    db.SaveChanges();

                    return true;
                }
                else
                {
                    //Se quiere eliminar uno de los roles fijos, no es posible.
                    return false;
                }
            }
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
             List<string> users = new List<string>();

            using (BibliotecaStore db = new BibliotecaStore())
            {

                if (usernameToMatch == null || usernameToMatch == "")
                {
                    //Si no se especifica un username, devuelvo todos los usuarios con ese rol.

                    TipoUsuario tipo = db.TipoUsuarios.Single(r => r.Descripcion == roleName);

                    var usuariosConRol = (from u in db.Usuarios
                                           where u.Tipo == tipo.IdTipoUser
                                           select u);

                    foreach (Usuario u in usuariosConRol)
                    {
                        CuentaUsuario cta_us = db.CuentaUsuarios.Single(c => c.Usuario == u.IdUsuario);
                        Cuenta cta = db.Cuentas.Single(c => c.IdCuenta == cta_us.Cuenta);

                        //Agrego el username
                        users.Add(cta.Usuario);
                    }

                }
                else
                {
                    //sino, asumiendo que cada usuario tiene un unico rol, devuelvo el rol para el usuario 'usernameToMatch'

                    //Busco el usuario 'usernameToMatch' y el rol que tiene asignado
                    Cuenta cta = db.Cuentas.Single(c => c.Usuario == usernameToMatch);
                    CuentaUsuario cta_us = db.CuentaUsuarios.Single(t => t.Cuenta == cta.IdCuenta);
                    Usuario user = db.Usuarios.Single(u => u.IdUsuario == cta_us.Usuario);
                    TipoUsuario tipo = db.TipoUsuarios.Single(r => r.IdTipoUser == user.Tipo);

                    //Busco el id del rol 'roleName'
                    int id_Match = db.TipoUsuarios.Single(r=>r.Descripcion==roleName).IdTipoUser;

                     //Si el rol que tiene asignado el usuario 'usernameToMatch' es exactamente 'roleName'
                    if (tipo.IdTipoUser == id_Match)
                    {
                        users.Add(cta.Usuario);
                    }
                    else
                    {
                        //Hay algo mal en la BD.... o en los parametros recibidos ?
                    }
                }

            }

            return users.ToArray();
        }

        public override string[] GetAllRoles()
        {
            List<string> roles = new List<string>();

            using (BibliotecaStore db = new BibliotecaStore())
            {
                try
                {
                    var dbRoles = from r in db.TipoUsuarios
                                  select r;

                    foreach (var role in dbRoles)
                    {
                        roles.Add(role.Descripcion);
                    }
                }
                catch
                {
                }
            }

            return roles.ToArray();
        }

        public override string[] GetRolesForUser(string username)
        {
            //Asumo que cada usuario tienen un unico rol
            List<string> roles = new List<string>();

            using (BibliotecaStore db = new BibliotecaStore())
            {
                //Busco el usuario 'username' y el rol que tiene asignado
                Cuenta cta = db.Cuentas.Single(c => c.Usuario == username);
                CuentaUsuario cta_us = db.CuentaUsuarios.Single(t => t.Cuenta == cta.IdCuenta);
                Usuario user = db.Usuarios.Single(u => u.IdUsuario == cta_us.Usuario);
                TipoUsuario tipo = db.TipoUsuarios.Single(r => r.IdTipoUser == user.Tipo);

                roles.Add(tipo.Descripcion);

                return roles.ToArray();
            }
        }

        public override string[] GetUsersInRole(string roleName)
        {
            List<string> users = new List<string>();
            //Devuelvo todos los usuarios con ese rol.
            using (BibliotecaStore db = new BibliotecaStore())
            {
                TipoUsuario tipo = db.TipoUsuarios.Single(r => r.Descripcion == roleName);

                var usuariosConRol = (from u in db.Usuarios
                                      where u.Tipo == tipo.IdTipoUser
                                      select u);

                foreach (Usuario u in usuariosConRol)
                {
                    CuentaUsuario cta_us = db.CuentaUsuarios.Single(c => c.Usuario == u.IdUsuario);
                    Cuenta cta = db.Cuentas.Single(c => c.IdCuenta == cta_us.Cuenta);

                    //Agrego el username
                    users.Add(cta.Usuario);
                }

                return users.ToArray();
            }
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            using (BibliotecaStore db = new BibliotecaStore())
            {
                Cuenta cta = db.Cuentas.Single(c => c.Usuario == username);
                CuentaUsuario cta_us = db.CuentaUsuarios.Single(t => t.Cuenta == cta.IdCuenta);
                Usuario user = db.Usuarios.Single(u => u.IdUsuario == cta_us.Usuario);
                TipoUsuario tipo = db.TipoUsuarios.Single(r => r.IdTipoUser == user.Tipo);

                //Si el tipo del usuario es 'roleName'
                if (tipo.Descripcion == roleName)
                    return true;

                else
                    return false;
               
            }
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        public override bool RoleExists(string roleName)
        {
            throw new NotImplementedException();
        }
    }
